package data

import (
	"context"
	"errors"

	"medicine/internal/biz"

	"github.com/go-kratos/kratos/v2/log"
	"gorm.io/gorm"
)

// pointsRepo 积分数据访问实现
type pointsRepo struct {
	data *DataRepo
	log  *log.Helper
}

// NewPointsRepo 创建积分数据访问实例
func NewPointsRepo(data *DataRepo, logger log.Logger) biz.PointsRepo {
	return &pointsRepo{
		data: data,
		log:  log.NewHelper(logger),
	}
}

// AddPoints 添加积分记录
func (r *pointsRepo) AddPoints(ctx context.Context, userID int64, points int64, pointsType string, description string, orderID int64) error {
	record := &biz.PointsRecord{
		UserID:      userID,
		Points:      points,
		Type:        pointsType,
		Description: description,
		OrderID:     orderID,
		CreatedAt:   r.data.DB.NowFunc(),
	}

	result := r.data.DB.WithContext(ctx).Create(record)
	if result.Error != nil {
		r.log.Errorf("添加积分记录失败: %v", result.Error)
		return result.Error
	}
	return nil
}

// GetUserPoints 获取用户积分
func (r *pointsRepo) GetUserPoints(ctx context.Context, userID int64) (int64, error) {
	var user biz.User
	result := r.data.DB.WithContext(ctx).Select("points").Where("id = ?", userID).First(&user)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return 0, nil
		}
		r.log.Errorf("获取用户积分失败: %v", result.Error)
		return 0, result.Error
	}
	return user.Points, nil
}

// GetPointsHistory 获取积分历史记录
func (r *pointsRepo) GetPointsHistory(ctx context.Context, userID int64, page, pageSize int) ([]*biz.PointsRecord, int, error) {
	var records []*biz.PointsRecord
	var total int64

	// 获取总记录数
	err := r.data.DB.WithContext(ctx).Model(&biz.PointsRecord{}).Where("user_id = ?", userID).Count(&total).Error
	if err != nil {
		r.log.Errorf("获取积分记录总数失败: %v", err)
		return nil, 0, err
	}

	// 获取分页记录
	offset := (page - 1) * pageSize
	result := r.data.DB.WithContext(ctx).
		Where("user_id = ?", userID).
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&records)

	if result.Error != nil {
		r.log.Errorf("获取积分历史记录失败: %v", result.Error)
		return nil, 0, result.Error
	}

	return records, int(total), nil
}

// GetPointsRule 获取积分规则
func (r *pointsRepo) GetPointsRule(ctx context.Context, ruleType string) (*biz.PointsRule, error) {
	var rule biz.PointsRule
	result := r.data.DB.WithContext(ctx).Where("type = ? AND enabled = ?", ruleType, true).First(&rule)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			// 返回默认规则
			return r.getDefaultRule(ruleType), nil
		}
		r.log.Errorf("获取积分规则失败: %v", result.Error)
		return nil, result.Error
	}
	return &rule, nil
}

// GetPointsRules 获取所有积分规则
func (r *pointsRepo) GetPointsRules(ctx context.Context) ([]*biz.PointsRule, error) {
	var rules []*biz.PointsRule
	result := r.data.DB.WithContext(ctx).Find(&rules)
	if result.Error != nil {
		r.log.Errorf("获取积分规则列表失败: %v", result.Error)
		return nil, result.Error
	}

	// 如果数据库中没有规则，返回默认规则
	if len(rules) == 0 {
		return r.getDefaultRules(), nil
	}

	return rules, nil
}

// InitDefaultRules 初始化默认积分规则
func (r *pointsRepo) InitDefaultRules(ctx context.Context) error {
	var count int64
	r.data.DB.Model(&biz.PointsRule{}).Count(&count)
	if count > 0 {
		r.log.Info("积分规则已存在，跳过初始化")
		return nil // 已有规则，跳过初始化
	}

	defaultRules := r.getDefaultRules()
	result := r.data.DB.WithContext(ctx).Create(&defaultRules)
	if result.Error != nil {
		r.log.Errorf("初始化默认积分规则失败: %v", result.Error)
		return result.Error
	}

	r.log.Infof("成功初始化 %d 条默认积分规则", len(defaultRules))
	return nil
}

// getDefaultRules 获取所有默认积分规则
func (r *pointsRepo) getDefaultRules() []*biz.PointsRule {
	return []*biz.PointsRule{
		{
			ID:          1,
			Type:        "consumption",
			Name:        "消费赠送积分",
			Description: "消费1元获得1积分",
			Rate:        1.0,
			MinAmount:   10,   // 最低消费10元
			MaxPoints:   1000, // 单次最多1000积分
			Enabled:     true,
		},
		{
			ID:          2,
			Type:        "checkin",
			Name:        "每日签到",
			Description: "每日签到获得5积分",
			Rate:        5.0,
			MinAmount:   0,
			MaxPoints:   5,
			Enabled:     true,
		},
	}
}

// getDefaultRule 获取默认积分规则
func (r *pointsRepo) getDefaultRule(ruleType string) *biz.PointsRule {
	defaultRules := r.getDefaultRules()
	for _, rule := range defaultRules {
		if rule.Type == ruleType {
			return rule
		}
	}

	// 如果没有找到对应的规则，返回通用默认规则
	return &biz.PointsRule{
		ID:          0,
		Type:        ruleType,
		Name:        "默认规则",
		Description: "默认积分规则",
		Rate:        1.0,
		MinAmount:   0,
		MaxPoints:   0,
		Enabled:     true,
	}
}
